/*
 * @Description: 穿梭框选中条目组件
 * @Author: Rfan
 * @Date: 2022-02-14 13:32:36
 * @LastEditTime: 2022-10-31 17:39:12
 */

import { useEffect, useRef, useState } from 'react';
import { Checkbox, Select } from 'antd';
import cs from 'classnames';
import classNames from 'classnames/bind';
import { useDrag, useDrop, XYCoord } from 'react-dnd';
import styles from '../styles/transferSelectItem.module.scss';

const cx = classNames.bind(styles);

const { Option } = Select;

const dragType = 'transferSelectItem';

const TransferSelectItem = (props: any) => {
  const { item, onItemSelect, selectedKeys, index, onChange, moveSelect, type } = props;
  const ref = useRef<HTMLDivElement>(null);

  const [isSelected, setIsSelected] = useState(false);

  const [{ handlerId }, drop] = useDrop({
    accept: dragType,
    collect(monitor) {
      return {
        handlerId: monitor.getHandlerId()
      };
    },
    hover(hItem: any, monitor) {
      if (!ref.current) {
        return;
      }
      const dragIndex = hItem.index;
      const hoverIndex = index;

      // Don't replace items with themselves
      if (dragIndex === hoverIndex) {
        return;
      }

      // Determine rectangle on screen
      const hoverBoundingRect = ref.current?.getBoundingClientRect();

      // Get vertical middle
      const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;

      // Determine mouse position
      const clientOffset = monitor.getClientOffset();

      // Get pixels to the top
      const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top;

      // Only perform the move when the mouse has crossed half of the items height
      // When dragging downwards, only move when the cursor is below 50%
      // When dragging upwards, only move when the cursor is above 50%

      // Dragging downwards
      if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
        return;
      }

      // Dragging upwards
      if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
        return;
      }

      // Time to actually perform the action
      moveSelect(dragIndex, hoverIndex);

      // Note: we're mutating the monitor item here!
      // Generally it's better to avoid mutations,
      // but it's good here for the sake of performance
      // to avoid expensive index searches.
      hItem.index = hoverIndex;
    }
  });

  const [{ isDragging }, drag] = useDrag({
    type: dragType,
    item: () => {
      return { key: item.key, index };
    },
    collect: (monitor: any) => ({
      isDragging: monitor.isDragging()
    })
  });

  const opacity = isDragging ? 0 : 1;

  useEffect(() => {
    setIsSelected(selectedKeys.indexOf(item.key) >= 0);
  }, [selectedKeys]);

  drag(drop(ref));
  /**
   * @description: 必选复选框
   * @param {any} val
   */
  const handleCheckChange = (val: any) => {
    item.required = val.target.checked;
    onChange(true);
  };
  /**
   * @description: 排序选择
   * @param {any} val
   */
  const handleSelectChange = (val: string) => {
    item.sortType = val;
    onChange(true);
  };
  return (
    <div
      ref={ref}
      className={cs('ant-transfer-list-content-item', cx('item-wrap'))}
      style={{ opacity }}
      key={item.key}
      data-handler-id={handlerId}
      onClick={() => onItemSelect(item.key, !isSelected)}
    >
      <div className={cx('title')}>
        <div className={cx('checkbox-wrap')}>
          <Checkbox checked={isSelected} />
        </div>
        {item.field_desc || item.fieldDesc}
      </div>
      {type === 1 ? (
        <div
          onClick={(evt) => {
            evt.stopPropagation();
          }}
        >
          <Checkbox defaultChecked={item.required} onChange={handleCheckChange}>
            必选
          </Checkbox>
        </div>
      ) : (
        <Select
          defaultValue={item.sortType || 0}
          style={{ width: 'auto' }}
          onChange={handleSelectChange}
          onClick={(evt) => {
            evt.stopPropagation();
          }}
        >
          <Option value={0}>升序</Option>
          <Option value={1}>降序</Option>
        </Select>
      )}
    </div>
  );
};

export default TransferSelectItem;
